/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** *****************************************************************************************************
 * \file     Mcu_CkgenDrv.c                                                                             *
 * \brief    AUTOSAR 4.3.1 MCAL Mcu Driver                                                              *
 *                                                                                                      *
 * <table>                                                                                              *
 * <tr><th>Date           <th>Version                                                                   *
 * <tr><td>2023/08/01     <td>1.0.0                                                                     *
 * </table>                                                                                             *
 *******************************************************************************************************/
/********************************************************************************************************
 *                                      Include header files                                            *
 *******************************************************************************************************/
#include "Mcu_CkgenDrv.h"
#include "Mcu_Ckgen.h"
#include "Mcal_Delay.h"
#include "Mcu_Clk.h"
#include "Mcu_Fault.h"

/********************************************************************************************************
 *                                 Private Macro definition                                             *
 *******************************************************************************************************/

#define ABS(x) (((sint32)(x) < 0) ? -(sint32)(x) : (sint32)(x))
#define MCU_DIV_ROUND_CLOSEST(n, d)     (((n) + ((d)/2U))/(d))
#define MCU_ROUND_UP(n) ((((n)/10U) + (5U)) / (10U) * (100U))

#define MCU_START_SEC_CODE
#include "Mcu_MemMap.h"

/********************************************************************************************************
 *                                  Private Function Declarations                                       *
 *******************************************************************************************************/
/** *****************************************************************************************************
 * \brief Determine if rate is closer to reference rate
 *
 * \verbatim
 * Syntax             : static boolean Mcu_Ip_CkgenDrvIsBetterRate(uint32 rate, uint32 now, uint32 best)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : rate - reference rate
 *                      now - rate to be judged
 *                      best - best rate ever
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : 1: closer, 0:other
 *
 * Description        : Determine if rate is closer to reference rate
 * \endverbatim
 *******************************************************************************************************/
static boolean Mcu_Ip_CkgenDrvIsBetterRate(uint32 rate, uint32 now, uint32 best)
{
    boolean ret;

    if (ABS((sint32)now - (sint32)rate) <= ABS((sint32)best - (sint32)rate))
    {
        ret = TRUE;
    }
    else
    {
        ret = FALSE;
    }

    return ret;
}

/** *****************************************************************************************************
 * \brief ip slice adaptively select parents.
 *
 * \verbatim
 * Syntax             : static uint8 Mcu_Ip_CkgenDrvIpSelectParent(const Mcu_ClkSliceNodeType *ipSlicePtr, Mcu_ClkRateType rate, uint32 *bestDivPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : ipSlicePtr - Pointer to clock node
 *                      rate - rate to set
 *
 * Parameters (inout) : bestDivPtr - pointer to the best div in best selected parents
 *
 * Parameters (out)   : None
 *
 * Return value       : best selected mux
 *
 * Description        : bus slice adaptively select parents. the closest rate will adaptively calculated.
 *                      the clock node mux and parent will be changed to the selected parents.
 * \endverbatim
 * Traceability       : SW_SM006
 *******************************************************************************************************/
static uint8 Mcu_Ip_CkgenDrvIpSelectParent(const Mcu_ClkSliceNodeType *ipSlicePtr, Mcu_ClkRateType rate,
        uint32 *bestDivPtr)
{
    const Mcu_ClkNodeType *parentPtr;
    Mcu_ClkRateType calcRate;
    Mcu_ClkRateType bestRate = 0;
    uint32 divNum;
    uint8 bestIndex = MCU_CLK_PARENT_NUM;
    uint8 i;
    Mcu_ClkRateType parentRate;
    boolean flag = FALSE;

    for (i = 0U; i < ipSlicePtr->parentsNum; i++)
    {
        /* check beyond max parent number */
        if (i >= MCU_CLK_PARENT_NUM)
        {
            flag = TRUE;
        }
        else
        {
            /* skip NULL parent */
            parentPtr = (const Mcu_ClkNodeType *)ipSlicePtr->parents[i];

            if (NULL_PTR == parentPtr)
            {
                continue;
            } /* else not needed */


            /* skip parent rate less then set rate */
            parentRate = Mcu_Ip_ClkGetRate(parentPtr);
            parentRate = MCU_ROUND_UP(parentRate);

            if (parentRate < rate)
            {
                continue;
            } /* else not needed */

            /* calculate divider for parent rate, and check divider validity */
            divNum = Mcu_Ip_CkgenGetBestDiv(parentRate, rate);

            if ((UINT32_MAX == divNum) || ((divNum - 1U) > 0xFFU))
            {
                continue;
            } /* else not needed */

            calcRate = parentRate / divNum;

            /* record best parent and divider */
            if (TRUE == Mcu_Ip_CkgenDrvIsBetterRate(rate, calcRate, bestRate))
            {
                bestRate = calcRate;
                bestIndex = i;
                *bestDivPtr = divNum;
            } /* else not needed */

            /* if choose xtal24m best, no need check pll */
            if ((rate == bestRate) && (1U == i))
            {
                flag = TRUE;
            } /* else not needed */
        }

        if (TRUE == flag)
        {
            break;
        }
    }

    return bestIndex;
}

/** *****************************************************************************************************
 * \brief bus slice adaptively select parents.
 *
 * \verbatim
 * Syntax             : static uint8 Mcu_Ip_CkgenDrvBusSelectParent(const Mcu_ClkSliceNodeType *busSlicePtr, Mcu_ClkRateType rate, uint32 *bestPreDivPtr, uint32 *mDivPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : busSlicePtr - Pointer to clock node
 *                      rate - rate to set
 *
 * Parameters (inout) : bestPreDivPtr - Pointer to the best div in best selected parents
 *                      mDivPtr - Pointer to best mvalue in best selected parents
 * bestDiv -
 *
 * Parameters (out)   : None
 *
 * Return value       : best selected mux
 *
 * Description        : bus slice adaptively select parents. the closest rate will adaptively calculated.
 *                      the clock node mux and parent will be changed to the selected parents.
 * \endverbatim
 * Traceability       : SW_SM006
 *******************************************************************************************************/
static uint8 Mcu_Ip_CkgenDrvBusSelectParent(const Mcu_ClkSliceNodeType *busSlicePtr, Mcu_ClkRateType rate,
        uint32 *bestPreDivPtr, uint32 *mDivPtr)
{
    Mcu_ClkNodeType const *parentPtr;
    Mcu_ClkRateType calcRate;
    Mcu_ClkRateType bestRate = 0U;
    uint32 divNum;
    uint8 bestIndex = MCU_CLK_PARENT_NUM;
    uint8 i;
    uint32 parentRate;
    boolean flag = FALSE;

    for (i = 0U; i < busSlicePtr->parentsNum; i++)
    {
        /* check beyond max parent number */
        if (i >= MCU_CLK_PARENT_NUM)
        {
            flag = TRUE;
        }
        else
        {
            parentPtr = busSlicePtr->parents[i];

            /* skip NULL parent */
            if (NULL_PTR == parentPtr)
            {
                continue;
            } /* else not needed */

            parentRate = Mcu_Ip_ClkGetRate(parentPtr);
            parentRate = MCU_ROUND_UP(parentRate);

            /* skip parent rate less then set rate */
            if (parentRate < rate)
            {
                continue;
            } /* else not needed */

            /* calculate divider for parent rate, and check divider validity */
            divNum = Mcu_Ip_CkgenGetBestDiv(parentRate, rate);

            if ((UINT32_MAX == divNum) || ((4U == i) ? (divNum > 0x10U) : (divNum > (0x20U * 0x10U))))
            {
                continue;
            } /* else not needed */

            /* record best parent and divider, go on for next parent */
            calcRate = parentRate / divNum;

            if (TRUE == Mcu_Ip_CkgenDrvIsBetterRate(rate, calcRate, bestRate))
            {
                bestRate = calcRate;
                bestIndex = i;

                if (i == 4U)
                {
                    *bestPreDivPtr = 1U;
                    *mDivPtr = divNum;
                }
                else if (divNum <= 0x20U)
                {
                    *bestPreDivPtr = divNum;
                    *mDivPtr = 1U;
                }
                else
                {
                    *bestPreDivPtr = 0x20U;
                    *mDivPtr = divNum / 0x20U;
                }
            } /* else not needed */

            /* if choose xtal24m best, no need check pll */
            if ((rate == bestRate) && (1U == i))
            {
                flag = TRUE;
            } /* else not needed */
        }

        if (TRUE == flag)
        {
            break;
        }
    }

    return bestIndex;
}

/********************************************************************************************************
 *                                  Global Function Declarations                                        *
 *******************************************************************************************************/
/** *****************************************************************************************************
 * \brief get best div closer to expected frequency
 *
 * \verbatim
 * Syntax             : uint32 Mcu_Ip_CkgenGetBestDiv(uint32 srcRef, uint32 freq)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : srcRef - reference frequency
 *                      freq - rate to set
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errID
 *
 * Description        : get best div closer to expected frequency
 * .
 * \endverbatim
 *******************************************************************************************************/
uint32 Mcu_Ip_CkgenGetBestDiv(uint32 srcRef, uint32 freq)
{
    uint32 clkDiv = UINT32_MAX;

    if (0U != freq)
    {
        clkDiv = MCU_DIV_ROUND_CLOSEST(srcRef, freq);
    } /* else not needed */

    /* The clkDiv greater than 1 and less than UINT32_MAX. */
    return clkDiv;
}
/** *****************************************************************************************************
 * \brief IP slice real frequency get by monitor.
 *
 * \verbatim
 * Syntax             : Mcu_ClkRateType Mcu_Ip_CkgenDrvIpMonGetRate(const Mcu_ClkNodeType *clkPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : clkPtr - Pointer to clock node
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : IP slice real frequency. UINT32_MAX means error.
 *
 * Description        : IP slice real frequency get by monitor.
 *
 * \endverbatim
 *******************************************************************************************************/
Mcu_ClkRateType Mcu_Ip_CkgenDrvIpMonGetRate(const Mcu_ClkNodeType *clkPtr)
{
    Mcu_ClkRateType rate = UINT32_MAX;

    if (clkPtr->type == CKGEN_IP_SLICE_TYPE)
    {
        rate = Mcu_Ip_CkgenIpMonGetRate(clkPtr->base, clkPtr->id, Mcu_Ip_CkgenDrvIpGetRate(clkPtr));
    }

    return rate;
}

/** *****************************************************************************************************
 * \brief IP slice register frequency get by register caculated.
 *
 * \verbatim
 * Syntax             : Mcu_ClkRateType Mcu_Ip_CkgenDrvIpGetRate(const Mcu_ClkNodeType *clkPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : clkPtr - Pointer to clock node
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : IP slice register frequency, not real frequency
 *
 * Description        : IP slice register frequency get by register caculated.
 * \endverbatim
 *******************************************************************************************************/
Mcu_ClkRateType Mcu_Ip_CkgenDrvIpGetRate(const Mcu_ClkNodeType *clkPtr)
{
    /* PRQA S 0310 1 */
    const Mcu_ClkSliceNodeType *ipSlicePtr = (const Mcu_ClkSliceNodeType *)clkPtr;
    const Mcu_ClkNodeType *parent;
    uint32 divNum;
    uint8 mux;
    Mcu_CkgenRateType parentRate;
    Mcu_CkgenRateType rate = UINT32_MAX;

    if ((NULL_PTR != ipSlicePtr) && (clkPtr->type == CKGEN_IP_SLICE_TYPE))
    {
        /* get slice rate from caculate register config */
        mux = Mcu_Ip_CkgenIpGetMux(clkPtr->base, clkPtr->id);

        divNum = Mcu_Ip_CkgenIpGetDiv(clkPtr->base, clkPtr->id);

        /* PRQA S 3432 1 */
        parent = CKGEN_SLICE_PARENT(ipSlicePtr, mux);

        parentRate = Mcu_Ip_ClkGetRate(parent);

        rate = (Mcu_CkgenRateType)parentRate / (Mcu_CkgenRateType)(divNum + 1U);
    }

    return rate;
}
/** *****************************************************************************************************
 * \brief ip slice frequency set.
 *
 * \verbatim
 * Syntax             : Std_ReturnType Mcu_Ip_CkgenDrvIpSetRate(const Mcu_ClkNodeType *clkPtr, Mcu_ClkRateType rate)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : clkPtr - Pointer to clock node
 *                      rate - rate to set
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errID
 *
 * Description        : ip slice frequency set.
 * \endverbatim
 * Traceability       : SW_SM006
 *******************************************************************************************************/
Std_ReturnType Mcu_Ip_CkgenDrvIpSetRate(const Mcu_ClkNodeType *clkPtr, Mcu_ClkRateType rate)
{
    Std_ReturnType errStatus = MCU_E_PARAM_POINTER;
    /* PRQA S 0310 1 */
    const Mcu_ClkSliceNodeType *ipSlicePtr = (const Mcu_ClkSliceNodeType *)clkPtr;
    uint8 mux;
    uint32 divNum = 0U;
    uint8 isLocked;

    if ((NULL_PTR != ipSlicePtr) && (clkPtr->type == CKGEN_IP_SLICE_TYPE))
    {
        /* select the suitable parent */
        mux = Mcu_Ip_CkgenDrvIpSelectParent(ipSlicePtr, rate, &divNum);

        if (MCU_CLK_PARENT_NUM == mux)
        {
            errStatus = MCU_E_PARAM_CONFIG;
        }
        else
        {
            /* if pll not ready, means this is the first config after reset,
            * don't change mux when pll is not ready. */
            isLocked = Mcu_Ip_ClkIsLocked(ipSlicePtr->parents[4]);

            McuFaultInj_Mcu_Ip_CkgenDrvIpSetRate_01();

            if ((0U == isLocked) || (0xFFU == isLocked))
            {
                errStatus = MCU_E_PLL_NOT_LOCKED;
            }
            else
            {
                errStatus = Mcu_Ip_CkgenIpSetRate(ipSlicePtr->clkNode.base, ipSlicePtr->clkNode.id, mux, divNum);
            }

        } /* else not needed */
    }

    return errStatus;
}

/** *****************************************************************************************************
 * \brief bus slice real frequency get by monitor.
 *
 * \verbatim
 * Syntax             : Mcu_ClkRateType Mcu_Ip_CkgenDrvBusMonGetRate(const Mcu_ClkNodeType *clkPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : clkPtr - Pointer to clock node
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : bus slice real frequency. UINT32_MAX means error.
 *
 * Description        : bus slice real frequency get by monitor.
 * \endverbatim
 *******************************************************************************************************/
Mcu_ClkRateType Mcu_Ip_CkgenDrvBusMonGetRate(const Mcu_ClkNodeType *clkPtr)
{
    Mcu_ClkRateType rate = UINT32_MAX;

    if (NULL_PTR != clkPtr)
    {
        if ((clkPtr->type == CKGEN_SF_BUS_SLICE_TYPE) || (clkPtr->type == CKGEN_BUS_SLICE_TYPE))
        {
            rate = Mcu_Ip_CkgenBusMonGetRate(clkPtr->base, clkPtr->id, CKGEN_BUS_ID_TYPE_DIV_M,
                                             Mcu_Ip_CkgenDrvBusGetRate(clkPtr));
        }
        else
        {
            ;
        }
    }


    return rate;
}

/** *****************************************************************************************************
 * \brief bus slice register frequency get by register caculated.
 *
 * \verbatim
 * Syntax             : Mcu_ClkRateType Mcu_Ip_CkgenDrvBusGetRate(const Mcu_ClkNodeType *clkPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : clkPtr - Pointer to clock node
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : bus slice register frequency, not real frequency
 *
 * Description        : bus slice register frequency get by register caculated.
 * \endverbatim
 *******************************************************************************************************/
Mcu_ClkRateType Mcu_Ip_CkgenDrvBusGetRate(const Mcu_ClkNodeType *clkPtr)
{
    Mcu_ClkRateType rate = UINT32_MAX;
    /* PRQA S 0310 1 */
    const Mcu_ClkSliceNodeType *busSlicePtr = (const Mcu_ClkSliceNodeType *)clkPtr;
    const Mcu_ClkNodeType *parent;
    uint32 parentRate;
    uint8 mux;

    if ((NULL_PTR != busSlicePtr) && ((CKGEN_SF_BUS_SLICE_TYPE == clkPtr->type)
                                      || (CKGEN_BUS_SLICE_TYPE == clkPtr->type)))
    {
        mux = Mcu_Ip_CkgenBusGetPreMux(clkPtr->base, clkPtr->id);

        /* PRQA S 3432 1 */
        parent = CKGEN_SLICE_PARENT(busSlicePtr, mux);

        parentRate = Mcu_Ip_ClkGetRate(parent);

        McuFaultInj_Mcu_Ip_CkgenDrvBusGetRate_01();

        if (UINT32_MAX != parentRate)
        {
            rate = Mcu_Ip_CkgenBusDivRootGetRate(clkPtr->base, clkPtr->id, parentRate);

            rate = Mcu_Ip_CkgenBusDivMnpqGetRate(clkPtr->base, clkPtr->id, CKGEN_BUS_ID_TYPE_DIV_M, rate);
        }
    }

    return rate;
}

/** *****************************************************************************************************
 * \brief bus slice frequency set.
 *
 * \verbatim
 * Syntax             : Std_ReturnType Mcu_Ip_CkgenDrvBusSetRate(const Mcu_ClkNodeType *clkPtr, Mcu_ClkRateType rate, Mcu_ClkBusRatioType postDiv)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : clkPtr - Pointer to clock node
 *                      rate - rate to set
 *                      postDiv - cpu/axi/apb ratio, CKGEN_BUS_DIV_4_2_1: 0, CKGEN_BUS_DIV_2_2_1: 1
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errID
 *
 * Description        : bus slice frequency set.
 * \endverbatim
 * Traceability       : SW_SM006
 *******************************************************************************************************/
Std_ReturnType Mcu_Ip_CkgenDrvBusSetRate(const Mcu_ClkNodeType *clkPtr, Mcu_ClkRateType rate,
        Mcu_ClkBusRatioType postDiv)
{
    Std_ReturnType errStatus = MCU_E_PARAM_POINTER;
    uint8 mux;
    uint32 preDiv = 0U;
    uint32 mDiv = 0U;
    uint8 isLocked;

    /* PRQA S 0310 1 */
    const Mcu_ClkSliceNodeType *busSlicePtr = (const Mcu_ClkSliceNodeType *)clkPtr;

    if ((NULL_PTR != busSlicePtr) && ((CKGEN_SF_BUS_SLICE_TYPE == clkPtr->type)
                                      || (CKGEN_BUS_SLICE_TYPE == clkPtr->type)))
    {
        /* force select post mux d0 */
        errStatus = Mcu_Ip_CkgenBusRootSetRate(clkPtr->base, clkPtr->id, 0U);

        if (E_OK == errStatus)
        {
            /* select best parent */
            mux = Mcu_Ip_CkgenDrvBusSelectParent(busSlicePtr, rate, &preDiv, &mDiv);

            if (MCU_CLK_PARENT_NUM != mux)
            {
                /* if pll not ready, means this is the first config after reset,
                * don't change mux when pll is not ready. */
                isLocked = Mcu_Ip_ClkIsLocked(busSlicePtr->parents[4]);

                McuFaultInj_Mcu_Ip_CkgenDrvBusSetRate_01();

                if ((0U == isLocked) || (0xFFU == isLocked))
                {
                    errStatus = MCU_E_PLL_NOT_LOCKED;
                }
                else
                {
                    /* set bus div root */
                    errStatus = Mcu_Ip_CkgenBusDivRootSetRate(clkPtr->base, clkPtr->type, clkPtr->id, mux, preDiv);

                    if (E_OK == errStatus)
                    {
                        /* set mnpq and ratio */
                        errStatus = Mcu_Ip_CkgenBusMnpqSetRate(clkPtr->base, clkPtr->id, postDiv, mDiv);
                    }
                }
            }
            else
            {
                errStatus = MCU_E_PARAM_CLOCK;
            }
        }
    }

    return errStatus;
}

/** *****************************************************************************************************
 * \brief Clock gate turn on in run mode.
 *
 * \verbatim
 * Syntax             : Std_ReturnType Mcu_Ip_CkgenDrvGatingEnable(const Mcu_ClkNodeType *clkPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : clkPtr - Pointer to clock node
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errID
 *
 * Description        : Clock gate turn on in run mode.
 *
 * \endverbatim
 * Traceability       : SW_SM006
 *******************************************************************************************************/
Std_ReturnType Mcu_Ip_CkgenDrvGatingEnable(const Mcu_ClkNodeType *clkPtr)
{
    uint32 base;
    uint32 id;
    Mcu_CkgenType cgType;
    uint32 type;
    Std_ReturnType errStatus = MCU_E_PARAM_POINTER;

    if (NULL_PTR != clkPtr)
    {
        base = clkPtr->base;
        id = clkPtr->id;
        cgType = clkPtr->type;

        if ((CKGEN_PCG_TYPE == cgType)  )
        {
            type = CKGEN_CG_ID_TYPE_PCG_TYPE;
            errStatus = Mcu_Ip_CkgenXcgSetGating(base, id, type, 1U);
        }
        else if (CKGEN_BCG_TYPE == cgType)
        {
            type = CKGEN_CG_ID_TYPE_BCG_TYPE;
            errStatus = Mcu_Ip_CkgenXcgSetGating(base, id, type, 1U);
        }
        else
        {
            errStatus = MCU_E_PARAM_CONFIG;
        }
    }

    return errStatus;
}
/** *****************************************************************************************************
 * \brief Clock gate turn off in run mode.
 *
 * \verbatim
 * Syntax             : Std_ReturnType Mcu_Ip_CkgenDrvGatingDisable(const Mcu_ClkNodeType *clkPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : clkPtr - Pointer to clock node
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errID
 *
 * Description        : Clock gate turn off in run mode.
 *
 * \endverbatim
 * Traceability       : SW_SM006
 *******************************************************************************************************/
Std_ReturnType Mcu_Ip_CkgenDrvGatingDisable(const Mcu_ClkNodeType *clkPtr)
{
    uint32 base;
    uint32 id;
    Mcu_CkgenType cgType;
    uint32 type;
    Std_ReturnType errStatus = MCU_E_PARAM_POINTER;

    if (NULL_PTR != clkPtr)
    {
        base = clkPtr->base;
        id = clkPtr->id;
        cgType = clkPtr->type;

        if ((CKGEN_PCG_TYPE == cgType)  )
        {
            type = CKGEN_CG_ID_TYPE_PCG_TYPE;
            errStatus = Mcu_Ip_CkgenXcgSetGating(base, id, type, 0U);
        }
        else if (CKGEN_BCG_TYPE == cgType)
        {
            type = CKGEN_CG_ID_TYPE_BCG_TYPE;
            errStatus = Mcu_Ip_CkgenXcgSetGating(base, id, type, 0U);
        }
        else
        {
            errStatus = MCU_E_PARAM_CONFIG;
        }
    }

    return errStatus;
}

/** *****************************************************************************************************
 * \brief get the clock gate state(Amon) by monitor.
 *
 * \verbatim
 * Syntax             : uint8 Mcu_Ip_CkgenDrvMonGatingIsGated(const Mcu_ClkNodeType *clkPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : clkPtr - Pointer to clock node
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : clock gate state
 *
 * Description        : get the clock gate state in run mode.
 *                      return 1 means gated, 0 means active.
 *                      return 0xFFu means error occurred.
 *
 * \endverbatim
 * Traceability       : SW_SM006
 *******************************************************************************************************/
uint8 Mcu_Ip_CkgenDrvMonGatingIsGated(const Mcu_ClkNodeType *clkPtr)
{
    uint32 base;
    uint32 id;
    Mcu_CkgenType cgType;
    uint8 gatedStatus = 0xFFu;
    Std_ReturnType errStatus;

    if (NULL_PTR != clkPtr)
    {
        base = clkPtr->base;
        id = clkPtr->id;
        cgType = clkPtr->type;

        errStatus = Mcu_Ip_CkgenMonEnable(base, cgType, id, 0U, TRUE);

        if (E_OK == errStatus)
        {
            /*after cg_amon_en, need wait 2 cycle(6M for default) to get cg gate status*/
            errStatus = Mcal_udelay(1);

            if (E_OK == errStatus)
            {
                gatedStatus = Mcu_Ip_CkgenGetReadyState(base, cgType, id);

                if (1U == gatedStatus)
                {
                    gatedStatus = 0U;
                }
                else
                {
                    gatedStatus = 1U;
                }
            } /*else not needed*/
        } /*else not needed*/
    }

    return gatedStatus;
}

/** *****************************************************************************************************
 * \brief get the clock gate state.
 *
 * \verbatim
 * Syntax             : uint8 Mcu_Ip_CkgenDrvGatingIsGated(const Mcu_ClkNodeType *clkPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : clkPtr - Pointer to clock node
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : clock gate state
 *
 * Description        : get the clock gate state in run mode.
 *                      return 1 means gated, 0 means active.
 *                      return 0xFFu means error occurred.
 *
 * \endverbatim
 * Traceability       : SW_SM006
 *******************************************************************************************************/
uint8 Mcu_Ip_CkgenDrvGatingIsGated(const Mcu_ClkNodeType *clkPtr)
{
    uint32 base;
    uint32 id;
    Mcu_CkgenType cgType;
    uint32 type;
    uint8 gatedStatus = 0xFFU;

    if (NULL_PTR != clkPtr)
    {
        base = clkPtr->base;
        id = clkPtr->id;
        cgType = clkPtr->type;

        if ((CKGEN_PCG_TYPE == cgType)  )
        {
            type = CKGEN_CG_ID_TYPE_PCG_TYPE;
            gatedStatus = Mcu_Ip_CkgenXcgIsGated(base, id, type);
        }
        else if (CKGEN_BCG_TYPE == cgType)
        {
            type = CKGEN_CG_ID_TYPE_BCG_TYPE;
            gatedStatus = Mcu_Ip_CkgenXcgIsGated(base, id, type);
        }
        else
        {
            gatedStatus = 0xFFU;
        }
    }

    return gatedStatus;
}

/** *****************************************************************************************************
 * \brief This function used for enable/disable slice frequency monitor.
 *
 * \verbatim
 * Syntax             : Std_ReturnType Mcu_Ip_CkgenDrvMonEnable(uint32 base, Mcu_CkgenType type, uint32 id, uint32 timeout, boolean enable)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - ckgen base
 *                      type - slice type
 *                      id - slice index
 *                      timeout - wdt timeout
 *                      enable - TRUE: enable, FALSE: disable
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : This function used for enable/disable slice frequency monitor.
 * \endverbatim
 *******************************************************************************************************/
Std_ReturnType Mcu_Ip_CkgenDrvMonEnable(uint32 base, Mcu_CkgenType type, uint32 id, uint32 timeout,
                                        boolean enable)
{
    return Mcu_Ip_CkgenMonEnable(base, type, id, timeout, enable);
}
/** *****************************************************************************************************
 * \brief enable/disable dbgMon monitor.
 *
 * \verbatim
 * Syntax             : Std_ReturnType Mcu_Ip_CkgenDrvDbgMonEnable(uint32 base, boolean enable)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - CKGEN base address
 *                      enable - TRUE/FALSE
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : enable/disable dbgMon monitor.
 *
 * \endverbatim
 *******************************************************************************************************/
Std_ReturnType Mcu_Ip_CkgenDrvDbgMonEnable(uint32 base, boolean enable)
{
    return Mcu_Ip_CkgenDbgMonEnable(base, enable);
}
/** *****************************************************************************************************
 * \brief config duty and jitter, enable/disable cqm monitor.
 *
 * \verbatim
 * Syntax             : void Mcu_Ip_CkgenDrvCqmEnable(uint32 base, uint32 cqmIndex, uint16 duty, uint16 jitter, boolean enable)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - CKGEN base address
 *                      duty - duty
 *                      jitter - jitter
 *                      enable - TRUE/FALSE
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : config duty and jitter, enable/disable cqm monitor.
 *
 * \endverbatim
 *******************************************************************************************************/
void Mcu_Ip_CkgenDrvCqmEnable(uint32 base, uint32 cqmIndex, uint16 duty, uint16 jitter,
                              boolean enable)
{
    Mcu_Ip_CkgenCqmEnable(base, cqmIndex, duty, jitter, enable);
}
/** *****************************************************************************************************
 * \brief This function monitor clock source ready and clock active.
 *
 * \verbatim
 * Syntax             : uint8 Mcu_Ip_CkgenMonDrvReady(Mcu_CkgenMonReadyType *ckgenMonReadyPtr)
 *
 * Service ID[hex]    : -
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : None
 *
 * Parameters (inout) : ckgenMonFreqPtr - Pointer to clock monitor node
 *                      typedef struct
                        {
                            uint32 base;
                            Mcu_ClkSliceType sliceType;(CKGEN_PCG_TYPE/CKGEN_BCG_TYPE/CKGEN_PLL_CG_TYPE/CKGEN_XTAL_CG_TYPE)
                            uint32 typeIndex;(slice id)
                            uint32 wdtTimeout;(wdtTimeout for xtal/pll ready)
                            uint8  monIntRes;(interrupt status, 0-no err, other-error occured)
                            uint32 realState;(real state)
                        } Mcu_CkgenMonReadyType;
 *
 * Parameters (out)   : None
 *
 * Return value       : clock monitor status
 *                      0 - the monitor status is ok
 *                      !0 - the monitor status is not ok
 *
 * Description        : This function monitor clock source ready and clock active.
 * \endverbatim
 * Traceability       : SWSR_MCU_049 SW_SM001
 *******************************************************************************************************/
uint8 Mcu_Ip_CkgenMonDrvReady(Mcu_CkgenMonReadyType *ckgenMonReadyPtr)
{
    uint8  ui8Res = 0xFFu;
    Std_ReturnType errStatus;

    if (NULL_PTR != ckgenMonReadyPtr)
    {
        /*disable ready monitor */
        errStatus = Mcu_Ip_CkgenMonEnable(ckgenMonReadyPtr->base, ckgenMonReadyPtr->type, ckgenMonReadyPtr->typeIndex,
                              ckgenMonReadyPtr->wdtTimeout, FALSE);

        if (E_OK == errStatus)
        {
            /*clear int status*/
            Mcu_Ip_CkgenClearIntStatus(ckgenMonReadyPtr->base, ckgenMonReadyPtr->type,
                                    ckgenMonReadyPtr->typeIndex);

            /*enable ready monitor */
            errStatus = Mcu_Ip_CkgenMonEnable(ckgenMonReadyPtr->base, ckgenMonReadyPtr->type, ckgenMonReadyPtr->typeIndex,
                                ckgenMonReadyPtr->wdtTimeout, TRUE);

            if (E_OK == errStatus)
            {
                /* get mon state */
                ckgenMonReadyPtr->realState = Mcu_Ip_CkgenGetReadyState(ckgenMonReadyPtr->base,
                                            ckgenMonReadyPtr->type, ckgenMonReadyPtr->typeIndex);

                /* get mon int state */
                ckgenMonReadyPtr->monIntRes = Mcu_Ip_CkgenGetIntStatus(ckgenMonReadyPtr->base,
                                            ckgenMonReadyPtr->type, ckgenMonReadyPtr->typeIndex);

                ui8Res = ckgenMonReadyPtr->monIntRes;
            } /* else not needed */
        } /* else not needed */

    } /* else not needed */

    return ui8Res;
}

/** *****************************************************************************************************
 * \brief Monitor Slice freq high or low  interface.
 *
 * \verbatim
 * Syntax             : uint8 Mcu_Ip_CkgenDrvMonFreq(Mcu_CkgenMonFreqType *ckgenMonFreqPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : None
 *
 * Parameters (inout) : ckgenMonFreqPtr - Pointer to clock monitor node
 *                      typedef struct
                        {
                            uint32 base;
                            Mcu_CkgenType sliceType;(CKGEN_IP_SLICE_TYPE/CKGEN_SF_BUS_SLICE_TYPE/MCU_BUS_SLICE/CKGEN_FS24M_TYPE)
                            uint32 typeIndex;(slice id)
                            uint32 sliceFreq;(Expected frequency)
                            uint8  freqTolerantRat;(Threshold percentage)
                            uint8  monIntRes;(interrupt status, 0-Frequency within threshold range, 1-Frequency out of threshold range, 0xFF-error occured)
                            uint32 realFreq;(real frequency)
                        } Mcu_CkgenMonFreqType;
 *
 * Parameters (out)   : None
 *
 * Return value       : clock monitor status
 *                      0 - the monitor status of clock rate is ok
 *                      !0 - the monitor status of clock rate is not ok
 *
 * Description        : This function monitor clock rate.
 * \endverbatim
 *******************************************************************************************************/
uint8 Mcu_Ip_CkgenDrvMonFreq(Mcu_CkgenMonFreqType *ckgenMonFreqPtr)
{
    uint8  ui8Res = 0xFFU;
    uint32 ui32MonSampleCount;
    uint16 ui16MonThrdLow;
    uint16 ui16MonThrdHigh;
    uint32 ui32MonSampleFreq;
    uint32 base;
    Std_ReturnType errStatus;

    if (NULL_PTR != ckgenMonFreqPtr)
    {

        base = ckgenMonFreqPtr->base;

        /* disable frequency monitor */
        errStatus = Mcu_Ip_CkgenMonEnable(base, ckgenMonFreqPtr->sliceType, ckgenMonFreqPtr->typeIndex, 0U,
                                          FALSE);

        if (E_OK == errStatus)
        {
            ui32MonSampleFreq = Mcu_Ip_CkgenGetMonitorClock(base, ckgenMonFreqPtr->sliceType,
                                ckgenMonFreqPtr->typeIndex, ckgenMonFreqPtr->sliceFreq);

            /* calcu the sampe count and the threshold count  */
            ui32MonSampleCount  = ckgenMonFreqPtr->sliceFreq / ui32MonSampleFreq ;
            ui16MonThrdLow     = (uint16)(ui32MonSampleCount - (ckgenMonFreqPtr->freqTolerantRat *
                                          ui32MonSampleCount / 100U));
            ui16MonThrdHigh    = (uint16)(ui32MonSampleCount + (ckgenMonFreqPtr->freqTolerantRat *
                                          ui32MonSampleCount / 100U));
            Mcu_Ip_CkgenSliceMonClrBusErrStatus(base, ckgenMonFreqPtr->sliceType,
                                                (uint8)ckgenMonFreqPtr->typeIndex);

            switch (ckgenMonFreqPtr->sliceType)
            {
            case CKGEN_IP_SLICE_TYPE:
                /*config ip slice threshold value */
                Mcu_Ip_CkgenIpMonSetThrd(base, ckgenMonFreqPtr->typeIndex, ui16MonThrdLow,
                                         ui16MonThrdHigh);
                /*get ip slice monitor real freq */
                ckgenMonFreqPtr->realFreq = Mcu_Ip_CkgenIpMonGetRate(base, ckgenMonFreqPtr->typeIndex,
                                            ckgenMonFreqPtr->sliceFreq);

                /* get ip slice mon int state */
                ckgenMonFreqPtr->monIntRes = Mcu_Ip_CkgenGetIntStatus(base, ckgenMonFreqPtr->sliceType,
                                             ckgenMonFreqPtr->typeIndex);

                break;

            case CKGEN_SF_BUS_SLICE_TYPE:
            case CKGEN_BUS_SLICE_TYPE:
                /*config bus slice threshold value */
                Mcu_Ip_CkgenBusMonSetThrd(base,  CKGEN_BUS_ID_TYPE_DIV_M, (ckgenMonFreqPtr->typeIndex), ui16MonThrdLow,
                                          ui16MonThrdHigh);
                /*get bus slice monitor real freq */
                ckgenMonFreqPtr->realFreq = Mcu_Ip_CkgenBusMonGetRate(base,  (ckgenMonFreqPtr->typeIndex),
                                            CKGEN_BUS_ID_TYPE_DIV_M, ckgenMonFreqPtr->sliceFreq);
                /* get bus slice mon int state */
                ckgenMonFreqPtr->monIntRes = Mcu_Ip_CkgenGetIntStatus(base, ckgenMonFreqPtr->sliceType,
                                             ckgenMonFreqPtr->typeIndex);

                break;

            case CKGEN_FS24M_TYPE:
                /*config bus slice threshold value */
                Mcu_Ip_Ckgen24MMonSetThrd(base, ui16MonThrdLow, ui16MonThrdHigh);
                /*get bus slice monitor real freq */
                ckgenMonFreqPtr->realFreq = Mcu_Ip_Ckgen24MMonGetRate(base);
                /* get 24M mon int state */
                ckgenMonFreqPtr->monIntRes = Mcu_Ip_CkgenGetIntStatus(base, ckgenMonFreqPtr->sliceType,
                                             ckgenMonFreqPtr->typeIndex);
                break;

            default:
                ckgenMonFreqPtr->monIntRes = 1U;
                break;
            }

            if (1U == ckgenMonFreqPtr->monIntRes)
            {
                ui8Res = 1U ;
            }
            else
            {
                ui8Res = 0U ;
            }
        } /* else not needed */

    } /* else not needed */

    return ui8Res;
}

/** *****************************************************************************************************
 * \brief Monitor DbgMon freq high or low  interface.
 *
 * \verbatim
 * Syntax             : uint8 Mcu_Ip_CkgenDrvDbgMonFreq(Mcu_CkgenMonFreqType *ckgenMonFreqPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : None
 *
 * Parameters (inout) : ckgenMonFreqPtr - Pointer to clock monitor node
 *                      typedef struct
                        {
                            uint32 base;
                            Mcu_CkgenType sliceType;(CKGEN_IP_SLICE_TYPE/CKGEN_SF_BUS_SLICE_TYPE/MCU_BUS_SLICE/CKGEN_EXT_TYPE)
                            uint32 typeIndex;(slice id)
                            uint32 sliceFreq;(Expected frequency)
                            uint8  freqTolerantRat;(Threshold percentage)
                            uint8  monIntRes;(interrupt status, 0-Frequency within threshold range, 1-Frequency out of threshold range, 0xFF-error occured)
                            uint32 realFreq;(real frequency)
                        } Mcu_CkgenMonFreqType;
 *
 * Parameters (out)   : None
 *
 * Return value       : clock monitor status
 *                      0 - the monitor status of clock rate is ok
 *                      !0 - the monitor status of clock rate is not ok
 *
 * Description        : This function monitor clock rate.
 * \endverbatim
 *******************************************************************************************************/
uint8 Mcu_Ip_CkgenDrvDbgMonFreq(Mcu_CkgenMonFreqType *ckgenMonFreqPtr)
{
    uint8  ui8Res = 0xFFu;
    uint32 ui32MonSampleCount;
    uint16 ui16MonThrdLow;
    uint16 ui16MonThrdHigh;
    uint32 ui32MonSampleFreq;
    uint32 base;
    Std_ReturnType errStatus;
    uint8 type = 0xFFU;

    if (NULL_PTR != ckgenMonFreqPtr)
    {

        base = ckgenMonFreqPtr->base;

        /* disable frequency monitor */
        errStatus = Mcu_Ip_CkgenDbgMonEnable(base, FALSE);

        if (E_OK == errStatus)
        {
            ui32MonSampleFreq = Mcu_Ip_CkgenGetDbgMonClock(base, ckgenMonFreqPtr->sliceFreq);

            /* calcu the sampe count and the threshold count  */
            ui32MonSampleCount  = ckgenMonFreqPtr->sliceFreq / ui32MonSampleFreq ;
            ui16MonThrdLow     = (uint16)(ui32MonSampleCount - (ckgenMonFreqPtr->freqTolerantRat *
                                          ui32MonSampleCount / 100U));
            ui16MonThrdHigh    = (uint16)(ui32MonSampleCount + (ckgenMonFreqPtr->freqTolerantRat *
                                          ui32MonSampleCount / 100U));
            Mcu_Ip_CkgenDbgMonClearIntState(base);

            switch (ckgenMonFreqPtr->sliceType)
            {
            case CKGEN_IP_SLICE_TYPE:
                type = 0U;
                break;

            case CKGEN_SF_BUS_SLICE_TYPE:
            case CKGEN_BUS_SLICE_TYPE:
                type = 1U;
                break;

            case CKGEN_EXT_TYPE:
                type = 3U;
                break;

            default:
                /* do nothing */
                break;
            }

            if (0xFFU != type)
            {
                /* select one slice for pll checking */
                Mcu_Ip_CkgenDbgMonSelect(base, type, ckgenMonFreqPtr->typeIndex);
                /*config pll threshold value */
                Mcu_Ip_CkgenDbgMonSetThrd(base, ui16MonThrdLow, ui16MonThrdHigh);
                /*get pll monitor real freq */
                ckgenMonFreqPtr->realFreq = Mcu_Ip_CkgenDbgMonGetRate(base, type, ckgenMonFreqPtr->typeIndex,
                                            ckgenMonFreqPtr->sliceFreq);

                /* get pll mon int state */
                ckgenMonFreqPtr->monIntRes = Mcu_Ip_CkgenDbgMonGetIntState(base);


                if (1U == ckgenMonFreqPtr->monIntRes)
                {
                    ui8Res = 1U ;
                }
                else
                {
                    ui8Res = 0U ;
                }
            } /* else not needed */

        } /* else not needed */

    } /* else not needed */

    return ui8Res;
}
/** *****************************************************************************************************
 * \brief Monitor clock duty and jitter interface.
 *
 * \verbatim
 * Syntax             : uint8 Mcu_Ip_CkgenDrvMonCqm(Mcu_CkgenCqmType *ckgenCqmPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : None
 *
 * Parameters (inout) : ckgenCqmPtr - pointer to ckgencqm struct
 *                      typedef struct
 *                      {
 *                          uint32 base;                (ckgen base )
 *                          uint32 cqmIndex;            (cqmIndex 0/1/2)
 *                          Mcu_CkgenType sliceType;    (slice type )
 *                          uint32 typeIndex;           (slice index )
 *                          uint8 dutyPercent;          (dutyPercent )
 *                          uint8 jitterPercent;        (jitterPercent )
 *                          uint8 dutyIntRes;           (interrupt status, 0-duty within threshold range, 1-duty out of threshold range, 0xFF-error occured )
 *                          uint8 jitterIntRes;         (interrupt status, 0-jitter within threshold range, 1-jitter out of threshold range, 0xFF-error occured )
 *                      } Mcu_CkgenCqmType;
 *
 * Parameters (out)   : None
 *
 * Return value       :  0:Duty jtter Normal      1: Duty jtter out of range    0xFF-error occured
 *
 * Description        : Monitor clock duty and jitter interface
 * \endverbatim
 *******************************************************************************************************/
uint8 Mcu_Ip_CkgenDrvMonCqm(Mcu_CkgenCqmType *ckgenCqmPtr)
{
    uint8 ui8Res = 0xFFu;
    uint8 ui8DutyConVal;
    uint8 ui8JitterConVal;
    uint8 errFlag = 0U;

    if (NULL_PTR != ckgenCqmPtr)
    {
        /*Disable cqm function */
        Mcu_Ip_CkgenCqmEnable(ckgenCqmPtr->base, ckgenCqmPtr->cqmIndex, 0U, 0U, FALSE);

        /*Clear cqm duty and jitter bit flag */
        Mcu_Ip_CkgenCqmClearDutyIntState(ckgenCqmPtr->base, ckgenCqmPtr->cqmIndex);
        Mcu_Ip_CkgenCqmClearJitterIntState(ckgenCqmPtr->base, ckgenCqmPtr->cqmIndex);

        /* ip slices select  */
        if (CKGEN_IP_SLICE_TYPE == ckgenCqmPtr->sliceType)
        {
            Mcu_Ip_CkgenDbgMonIpSelect(ckgenCqmPtr->base, ckgenCqmPtr->typeIndex, 1U);
        }
        /* bus slices select  */
        else if ((CKGEN_SF_BUS_SLICE_TYPE == ckgenCqmPtr->sliceType)
                 || (CKGEN_BUS_SLICE_TYPE == ckgenCqmPtr->sliceType))
        {
            Mcu_Ip_CkgenDbgMonBusSelect(ckgenCqmPtr->base, ckgenCqmPtr->typeIndex, 1U);
        }
        else if (CKGEN_EXT_TYPE == ckgenCqmPtr->sliceType)
        {
            Mcu_Ip_CkgenDbgMonExtSelect(ckgenCqmPtr->base, ckgenCqmPtr->typeIndex, 1U);
        }
        else
        {
            errFlag = 1U;
        }

        if (0U == errFlag)
        {
            /*Duty-Percent converts specific values*/
            ui8DutyConVal = MCU_DIV_ROUND_CLOSEST((ckgenCqmPtr->dutyPercent * 2U * 64U), 100U) ;

            /*Jitter-Percent converts specific values*/
            ui8JitterConVal = MCU_DIV_ROUND_CLOSEST((ckgenCqmPtr->jitterPercent * 2U * 64U), 100U) ;

            if (0U == ui8DutyConVal)
            {
                ui8DutyConVal = 1U ;
            } /* else not needed */

            if (0U == ui8JitterConVal)
            {
                ui8JitterConVal = 1U ;
            } /* else not needed */

            /*config cqm jitter and duty*/
            Mcu_Ip_CkgenCqmEnable(ckgenCqmPtr->base, ckgenCqmPtr->cqmIndex, ui8DutyConVal,
                                  ui8JitterConVal, TRUE);

            /*get  cqm  duty and jitter int state */
            ckgenCqmPtr->dutyIntRes    = Mcu_Ip_CkgenCqmGetDutyIntState(ckgenCqmPtr->base,
                                         ckgenCqmPtr->cqmIndex);
            ckgenCqmPtr->jitterIntRes  = Mcu_Ip_CkgenCqmGetJitterIntState(ckgenCqmPtr->base,
                                         ckgenCqmPtr->cqmIndex);

            /*Duty and Jitter reslut judgement */
            if ((1U == ckgenCqmPtr->dutyIntRes) || (1U == ckgenCqmPtr->jitterIntRes))
            {
                ui8Res = 1U ;
            }
            else
            {
                ui8Res = 0U ;
            }
        } /* else not needed */
    } /* else not needed */

    return ui8Res;
}

/** *****************************************************************************************************
 * \brief This function used for debug to pull clock nodes to pad to measure frequency.
 *
 * \verbatim
 * Syntax             : Std_ReturnType Mcu_Ip_CkgenClockToPad(const Mcu_ClkNodeType *ckgenPtr, uint8 divNum)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : ckgenPtr - clock note with type Mcu_CkgenNodeType defined in "Mcu_ClkCfgNode.h"
 *                      divNum - frequency division
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *                      E_OK for success and others for failure.
 *
 * Description        : This function used for debug to pull clock nodes to pad to measure frequency.
 *                      GPIO_A9/A10/A11 need MUX CKGEN_SF.CLK_DBG, GPIO_LA4/LA5/LA6 need MUX CKGEN_LPP.CLK_DBG
 * \endverbatim
 *******************************************************************************************************/
Std_ReturnType Mcu_Ip_CkgenClockToPad(const Mcu_ClkNodeType *ckgenPtr, uint8 divNum)
{
    Std_ReturnType errStatus = E_OK;

    if ((NULL_PTR != ckgenPtr) && (divNum >= 1U) && (divNum <= 15U))
    {
        if (CKGEN_IP_SLICE_TYPE == ckgenPtr->type)
        {
            Mcu_Ip_CkgenDbgMonIpSelect(ckgenPtr->base, ckgenPtr->id, divNum);
        }
        else if ((CKGEN_SF_BUS_SLICE_TYPE == ckgenPtr->type) || (CKGEN_BUS_SLICE_TYPE == ckgenPtr->type))
        {
            Mcu_Ip_CkgenDbgMonBusSelect(ckgenPtr->base, ckgenPtr->id, divNum);
        }
        else if (CKGEN_EXT_TYPE == ckgenPtr->type)
        {
            Mcu_Ip_CkgenDbgMonExtSelect(ckgenPtr->base, ckgenPtr->id, divNum);
        }
        else
        {
            errStatus = MCU_E_PARAM_CONFIG;
        }
    }
    else
    {
        errStatus = MCU_E_PARAM_POINTER;
    }

    return errStatus;
}
#define MCU_STOP_SEC_CODE
#include "Mcu_MemMap.h"
/* End of file */
